Skip to content

Issues backlog: PhoneApp onDestroyed, custom commands enhancement, employee appearances, more checks in CombatBehaviour#84

Merged
ifBars merged 5 commits into
ifBars:stablefrom
k073l:backlog
Jun 9, 2026
Merged

Issues backlog: PhoneApp onDestroyed, custom commands enhancement, employee appearances, more checks in CombatBehaviour#84
ifBars merged 5 commits into
ifBars:stablefrom
k073l:backlog

Conversation

@k073l

@k073l k073l commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Closes a bunch of issues: #74, #76, #83.

Also closes one issue from Trello - custom commands now appear in the command list screen, just like native commands do.

Release Notes

  • PhoneApp lifecycle management: Implemented OnDestroy() wiring for PhoneAppButtonHandler to properly tear down the associated PhoneApp when the button handler component is destroyed
  • Custom commands UI integration: Custom commands now appear in the command list screen alongside native commands via updated console patches
  • Employee appearance API: Exposed employee appearance data through new EmployeeManager and EmployeeAppearance wrapper classes with access to appearance settings and mugshots
  • Combat behavior improvements: Refactored CombatBehaviour.DefaultWeaponAssetPath setter with safer type casting using CrossType.Is checks, switched to melonlogger for error reporting, and updated XML documentation
  • Internal registry accessibility: Made CustomConsoleRegistry.registry internal to support assembly-level access for custom command integration

Contributions by Author

Author Lines Added Lines Removed Net Change
k0 93 8 +85
ifBars 89 1 +88
Total 182 9 +173

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ifBars, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 55 minutes and 15 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 469dc46f-f99b-4977-8e45-d22e743d26c0

📥 Commits

Reviewing files that changed from the base of the PR and between b6197c2 and 6d00589.

📒 Files selected for processing (5)
  • S1API/Console/CustomConsoleRegistry.cs
  • S1API/Entities/Behaviour/CombatBehaviour.cs
  • S1API/Entities/Employees/EmployeeManager.cs
  • S1API/Internal/Patches/ConsolePatches.cs
  • S1API/PhoneApp/PhoneApp.cs
📝 Walkthrough

Walkthrough

This PR enhances console command registration, adds a type-safe employee appearance API, and improves error handling with centralized logging and component lifecycle management. The custom console registry is exposed to allow UI injection patches to register commands in the in-game command list, the new EmployeeManager provides safe access to base-game employee data, and CombatBehaviour refactors error reporting through Logger while PhoneAppButtonHandler ensures proper cleanup.

Changes

Custom Console Commands UI Integration

Layer / File(s) Summary
Registry accessibility for patch integration
S1API/Console/CustomConsoleRegistry.cs
CustomConsoleRegistry's registry field changes from private to internal, enabling ConsolePatches to access and iterate registered custom commands.
Console command list UI patch and injection
S1API/Internal/Patches/ConsolePatches.cs
ConsolePatches adds Harmony postfix for S1CommandListScreen.Start to inject custom command entries into the in-game command list UI, handling deduplication and both IL2CPP and Mono builds. Conditional usings route to correct IL2CPP types.

Employee Appearance Wrapper API

Layer / File(s) Summary
Employee appearance wrapper types and API
S1API/Entities/Employees/EmployeeManager.cs
New EmployeeManager with GetAppearance and GetRandomAppearance static methods safely query the base-game employee system with null checks and error logging. EmployeeAppearance wraps appearance data (Settings, Mugshot) with conditional compilation for IL2CPP vs Mono.

Error Handling and Component Lifecycle Management

Layer / File(s) Summary
CombatBehaviour weapon-loading error handling
S1API/Entities/Behaviour/CombatBehaviour.cs
Adds Logger instance and refactors DefaultWeaponAssetPath setter to use CrossType.Is validation checks and centralized Logger.Error instead of Debug.LogError, with early return on validation failure. XML documentation updated with preferred setter guidance.
PhoneApp component cleanup on destroy
S1API/PhoneApp/PhoneApp.cs
PhoneAppButtonHandler implements OnDestroy lifecycle hook to call DestroyInternal on its associated PhoneApp, ensuring proper teardown when the handler component is destroyed.

Sequence Diagram(s)

sequenceDiagram
  participant CommandListScreen
  participant ConsolePatches
  participant CustomConsoleRegistry
  participant UIContainer
  CommandListScreen->>ConsolePatches: S1CommandListScreen.Start (Harmony postfix)
  ConsolePatches->>CustomConsoleRegistry: iterate registry.Keys
  loop For each custom command
    ConsolePatches->>UIContainer: instantiate command entry prefab
    ConsolePatches->>UIContainer: populate Command/Description/Example text
    ConsolePatches->>UIContainer: append entry to commandEntries
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

bug

Suggested reviewers

  • ifBars

Poem

🐰 A rabbit hops through console halls,
With custom commands now on call,
Employee data wrapped up tight,
PhoneApp cleanup, lifecycle right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title addresses multiple unrelated changes across different features (PhoneApp, custom commands, employee appearances, CombatBehaviour), making it overly broad and generic without clearly conveying the main purpose of the changeset. Consider using a more focused title that either highlights the primary feature or uses a structured format like 'Backlog improvements' with detailed changelog in the description.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 60.00% which is sufficient. The required threshold is 50.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added the bug Something isn't working label Jun 5, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
S1API/Console/CustomConsoleRegistry.cs (1)

14-14: ⚡ Quick win

Keep the registry encapsulated.

ConsolePatches only needs to enumerate commands. Making the field itself internal lets any internal caller bypass Register()'s trim/empty-key checks and mutate the dictionary directly. Expose a read-only view or iterator instead.

Suggested change
-        internal static readonly Dictionary<string, BaseConsoleCommand> registry = new Dictionary<string, BaseConsoleCommand>(StringComparer.OrdinalIgnoreCase);
+        private static readonly Dictionary<string, BaseConsoleCommand> registry = new Dictionary<string, BaseConsoleCommand>(StringComparer.OrdinalIgnoreCase);
+        internal static IReadOnlyDictionary<string, BaseConsoleCommand> Registry => registry;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@S1API/Console/CustomConsoleRegistry.cs` at line 14, The registry field is
currently internal which allows bypassing Register() validations; make the
dictionary private (private static readonly Dictionary<string,
BaseConsoleCommand> registry) and expose a read-only view or enumerator instead
(for example a public/static IReadOnlyDictionary<string, BaseConsoleCommand> or
a method IEnumerable<KeyValuePair<string,BaseConsoleCommand>>
GetRegisteredCommands()) so ConsolePatches can enumerate without mutating; keep
Register() (and its trim/empty-key checks) as the single mutating entry point
and return or expose only the read-only wrapper from the new accessor.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@S1API/Entities/Behaviour/CombatBehaviour.cs`:
- Around line 92-93: The DefaultWeaponAssetPath setter currently calls
Object.Instantiate(gameObject) and then GetComponent<AvatarEquippable>, which
creates an undeleted runtime clone; instead, remove the Instantiate call and
validate the assigned prefab directly by calling
GetComponent<AvatarEquippable>() or GetComponentInChildren<AvatarEquippable>()
on the prefab reference (or this.gameObject/prefab variable used in the setter)
to check for AvatarEquippable, and keep the existing null-handling (log/throw)
path if the component is missing.

In `@S1API/Entities/Employees/EmployeeManager.cs`:
- Line 33: The wrapper must guard against nulls from the underlying API: change
the EmployeeManager appearance wrapper so that when
S1Employees.EmployeeManager.Instance.GetAppearance(male, index) returns null you
return null (or propagate appropriately) instead of always calling new
EmployeeAppearance(...); similarly update GetRandomAppearance to use the out
AvatarSettings? avatarSettings only if the base call returns true and
avatarSettings is non-null — do not always construct new
AvatarSettings(avatarSettings) or always return true; instead call
S1Employees.EmployeeManager.Instance.GetRandomAppearance(...) and if it returns
false or the out avatarSettings is null, set the wrapper out to null and return
false, otherwise construct new AvatarSettings(avatarSettings) and return true.
Ensure you reference EmployeeAppearance, EmployeeManager.Instance.GetAppearance,
GetRandomAppearance, AvatarSettings and the avatarSettings out parameter when
applying the checks.

In `@S1API/Internal/Patches/ConsolePatches.cs`:
- Line 43: The static HashSet _addedCommandsToList is being cleared only in
AddCommands() via S1Console.Awake which prevents newly created
S1CommandListScreen instances from receiving custom entries; move or add the
reset so duplicate tracking is cleared at the start of each command-list screen
creation by clearing _addedCommandsToList at the beginning of
AddCustomCommandEntries() (or change dedupe to an instance-scoped set inside
S1CommandListScreen) so each S1CommandListScreen gets its own fresh tracking and
custom keys are added correctly.
- Around line 174-189: The postfix currently adds custom command entries even
when their CommandWord collides with a built-in command; before instantiating or
adding an entry inside the foreach over CustomConsoleRegistry.registry.Keys,
check for collisions with the game's native registry (e.g., S1Console.commands
or the equivalent built-in command map) and skip entries whose key already
exists there so only executable custom commands are shown; update the logic
around CustomConsoleRegistry.registry, _addedCommandsToList, CommandEntryPrefab
and CommandEntryContainer to continue when a built-in command owns the key.

In `@S1API/PhoneApp/PhoneApp.cs`:
- Around line 651-655: OnDestroy currently unconditionally calls DestroyInternal
and can re-enter destruction when PhoneApp.OnDestroyed destroys _appPanel (which
tears down the handler); add a re-entrancy guard: introduce a private bool
(e.g., _isDestroying) on PhoneApp, set it true at the start of DestroyInternal
(or OnDestroyed) and skip any further destruction if it's already true, and
update OnDestroy to check that flag (or phoneApp != null &&
!phoneApp._isDestroying) before calling DestroyInternal to prevent double runs.

---

Nitpick comments:
In `@S1API/Console/CustomConsoleRegistry.cs`:
- Line 14: The registry field is currently internal which allows bypassing
Register() validations; make the dictionary private (private static readonly
Dictionary<string, BaseConsoleCommand> registry) and expose a read-only view or
enumerator instead (for example a public/static IReadOnlyDictionary<string,
BaseConsoleCommand> or a method
IEnumerable<KeyValuePair<string,BaseConsoleCommand>> GetRegisteredCommands()) so
ConsolePatches can enumerate without mutating; keep Register() (and its
trim/empty-key checks) as the single mutating entry point and return or expose
only the read-only wrapper from the new accessor.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ddf3d5e3-e041-4fb5-ab8d-cc937bd56ae3

📥 Commits

Reviewing files that changed from the base of the PR and between f6dfcfc and b6197c2.

📒 Files selected for processing (5)
  • S1API/Console/CustomConsoleRegistry.cs
  • S1API/Entities/Behaviour/CombatBehaviour.cs
  • S1API/Entities/Employees/EmployeeManager.cs
  • S1API/Internal/Patches/ConsolePatches.cs
  • S1API/PhoneApp/PhoneApp.cs

Comment thread S1API/Entities/Behaviour/CombatBehaviour.cs Outdated
Comment thread S1API/Entities/Employees/EmployeeManager.cs Outdated
Comment thread S1API/Internal/Patches/ConsolePatches.cs Outdated
Comment thread S1API/Internal/Patches/ConsolePatches.cs Outdated
Comment thread S1API/PhoneApp/PhoneApp.cs
@ifBars ifBars merged commit 9fc3f7f into ifBars:stable Jun 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

2 participants